package com.example.portablefortheelderlybackground.sevice.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.portablefortheelderlybackground.common.StringCommon;
import com.example.portablefortheelderlybackground.common.key.paramsKey;
import com.example.portablefortheelderlybackground.common.redis.redisKey;
import com.example.portablefortheelderlybackground.mapper.questionMapper;
import com.example.portablefortheelderlybackground.pojo.question.answer;
import com.example.portablefortheelderlybackground.pojo.question.question;
import com.example.portablefortheelderlybackground.sevice.SurveyRelationQuestionService;
import com.example.portablefortheelderlybackground.sevice.answerService;
import com.example.portablefortheelderlybackground.sevice.questionService;
import com.example.portablefortheelderlybackground.utils.Response;
import com.example.portablefortheelderlybackground.vo.questionVo.topicVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import static com.example.portablefortheelderlybackground.Enum.Message.ReturnMessageEnum.*;
//todo 添加redis缓存

@Service
@Slf4j
@Transactional(timeout = 5)
public class questionServiceImpl extends ServiceImpl<questionMapper, question> implements questionService {

    private final
    answerService answerService;
    private final SurveyRelationQuestionService surveyRelationQuestionService;
    private final
    RedisTemplate<String, Object> redisTemplate;

    @Autowired
    public questionServiceImpl(answerService answerService, SurveyRelationQuestionService surveyRelationQuestionService, RedisTemplate<String, Object> redisTemplate) {
        this.answerService = answerService;
        this.surveyRelationQuestionService = surveyRelationQuestionService;
        this.redisTemplate = redisTemplate;
    }

    @Override
    public IPage<topicVo> getAllTopicVo(IPage<topicVo> page, String type) {
        IPage<topicVo> redisTopicVo = (IPage<topicVo>) redisTemplate.opsForValue().get(redisKey.questionQueryKey + type);
        if (!ObjectUtils.isEmpty(redisTopicVo)) {
            return redisTopicVo;
        }
        //查询问题的数量
        Integer integer = baseMapper.selectCount(new LambdaQueryWrapper<>());
        integer = integer == null ? 0 : integer * 5;
        IPage<topicVo> allTopicVo = baseMapper.getAllTopicVo(page.setSize(integer), type);
        redisTemplate.opsForValue().set(redisKey.questionQueryKey + type, allTopicVo, StringCommon.TimeOut, TimeUnit.HOURS);
        return allTopicVo;
    }

    @Override
    public topicVo getTopicVoById(String id) {
        topicVo redisTopicVo = (topicVo) redisTemplate.opsForValue().get(redisKey.questionKey + id);
        if (!ObjectUtils.isEmpty(redisTopicVo)) {
            return redisTopicVo;
        }
        question question = baseMapper.selectById(id);
        topicVo topicVo = new topicVo();
        LambdaQueryWrapper<answer> queryWrapper = new LambdaQueryWrapper<>();
        boolean empty = ObjectUtils.isEmpty(question);
        queryWrapper.eq(!empty, answer::getQuestionId, question.getId());
        BeanUtils.copyProperties(question, topicVo);
        topicVo.setAnswerList(answerService.list(queryWrapper));
        if (empty) {
            redisTemplate.opsForValue().set(redisKey.questionKey + id, topicVo, StringCommon.TimeOut, TimeUnit.HOURS);
        }
        return !empty ? topicVo : null;
    }

    @Override
    public Response<Boolean> deleteQuestionsBatch(String[] ids) {
        int i = baseMapper.deleteByIds(ids);
        //判断i是否大于1
        boolean b;
        if (i > paramsKey.NUM_ZERO) {
            //执行删除answer
            b = answerService.removeByIds(Arrays.asList(ids));
        } else {
            //如果i不大于0,即删除失败,事务回滚
            //todo 考虑全局异常捕获
            return Response.status(false, DELETE_ERROR.getCode(), DELETE_ERROR.getMessage());
        }
        if (b) {
            //如果删除成功,清楚redis缓存
            //获取question
            List<question> questions = baseMapper.selectBatchIds(List.of(ids));
            //构建无序且不重复的set
            Set<String> questionTypeSet = new HashSet<>();
            questions.forEach(t -> {
                //添加对应的redisKey,且去重
                questionTypeSet.add(redisKey.questionQueryKey + t.getType());
            });
            List<String> list = Arrays.asList(ids);
            List<String> answerList = list.stream().map(t -> redisKey.answerKey + t).toList();
            List<String> questionList = list.stream().map(t -> redisKey.questionKey + t).toList();
            //清楚对应answer的缓存
            redisTemplate.opsForValue().getOperations().delete(answerList);
            //清楚对应的question的缓存
            redisTemplate.opsForValue().getOperations().delete(questionList);
            //清除对应question的queryKey
            redisTemplate.opsForValue().getOperations().delete(questionTypeSet);
        }
        return Response.status(b, DELETE_SUCCESS.getCode(), DELETE_SUCCESS.getMessage());
    }

    @Override
    public Response<topicVo> addQuestion(topicVo topicVo) {
        question question = new question();
        BeanUtils.copyProperties(topicVo, question, "serialVersionUID", "answerList");
        int insert = baseMapper.insert(question.setAnswerId("0"));
        //新增answer数组,新增之前,将question的id存放至每个answer中
        topicVo.getAnswerList().forEach(t -> {
            t.setQuestionId(question.getId());
        });
        boolean saveBatch = answerService.saveBatch(topicVo.getAnswerList());
        //清除对应的type缓存
        redisTemplate.opsForValue().getOperations().delete(redisKey.questionQueryKey + question.getType());
        //设置问题id
        topicVo.setId(question.getId());
        return Response.status(topicVo, SAVE_SUCCESS.getCode(), SAVE_SUCCESS.getMessage());
    }

    @Override
    public IPage<topicVo> getAllTopicVoById(IPage<topicVo> page, String id) {
        //不考虑三张表进行联查
        //去查询关系对应表,获得关于id的list
        List<String> questionIdListBySurveyId = surveyRelationQuestionService.getQuestionIdListBySurveyId(id);
        //判断是否为空
        if (ObjectUtils.isEmpty(questionIdListBySurveyId)) {
            throw new NullPointerException("数据库繁忙或者数据为空!");
        }
        //根据获取到id集合查询topicVo
        return baseMapper.getAllTopicVoById(page, questionIdListBySurveyId);
    }
}
